#include "StdAfx.h"

#include "../ColorUtils/Color.h"
#include "../ColorUtils/Image.h"

#include "MathUtils/Ray.h"
#include "FirstIntersectionResult.h"
#include "SecondIntersectionResult.h"
#include "Intersectable.h"
#include "FlatRectangle.h"
#include "TexturedRectangle.h"

#include "TexturedBox.h"

TexturedBox::TexturedBox(const Point& p0, const Point& p1, const Point& p2, const Point& p3, const Image_ptr textureImage) : _image(textureImage)
{
	Point vec1 = p1 - p0, vec2 = p2 - p0, vec3 = p3 - p0;
	if(Point(vec1.Y * vec2.Z - vec1.Z * vec2.Y, vec1.Z * vec2.X - vec1.X * vec2.Z, vec1.X * vec2.Y - vec1.Y * vec2.X).ScalarProduct(vec3) < 0)
	{
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p0, p1, p2, textureImage)));
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p3, p2 + vec3, p1 + vec3, textureImage)));
	}
	else
	{
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p0, p2, p1, textureImage)));
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p3, p1 + vec3, p2 + vec3, textureImage)));
	}

	if(Point(vec1.Y * vec3.Z - vec1.Z * vec3.Y, vec1.Z * vec3.X - vec1.X * vec3.Z, vec1.X * vec3.Y - vec1.Y * vec3.X).ScalarProduct(vec2) < 0)
	{
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p0, p1, p3, textureImage)));
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p2, p3 + vec2, p1 + vec2, textureImage)));
	}
	else
	{
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p0, p3, p1, textureImage)));
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p2, p1 + vec2, p3 + vec2, textureImage)));
	}

	if(Point(vec3.Y * vec2.Z - vec3.Z * vec2.Y, vec3.Z * vec2.X - vec3.X * vec2.Z, vec3.X * vec2.Y - vec3.Y * vec2.X).ScalarProduct(vec1) < 0)
	{
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p0, p3, p2, textureImage)));
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p1, p2 + vec1, p3 + vec1, textureImage)));
	}
	else
	{
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p0, p2, p3, textureImage)));
		_rectangles.push_back(TexturedRectangle_ptr(new TexturedRectangle(p1, p3 + vec1, p2 + vec1, textureImage)));
	}
}

void TexturedBox::WhereIntersects(const Ray& ray, FirstIntersectionResult& result)
{
	Point dummyPoint(0, 0, 0);
	int count = 0;
	bool isNotInside = true;

	for (std::vector<boost::shared_ptr<TexturedRectangle>>::iterator iter = _rectangles.begin(); iter != _rectangles.end(); iter++, count++)
	{
		Direction tempNormal = (*iter)->NormalAtPoint(result, dummyPoint);
		if (tempNormal.ScalarProduct(ray.D) < 0)
		{
			(*iter)->WhereIntersects(ray, result);
			if (result.DoesIntersect())
			{
				isNotInside = false;
				result.ExtraInfoDouble = count;
				return;
			}
		}
	}

	count = 0;
	if (isNotInside)
	{
		for (std::vector<boost::shared_ptr<TexturedRectangle>>::iterator iter = _rectangles.begin(); iter != _rectangles.end(); iter++, count++)
		{
			Direction tempNormal = (*iter)->NormalAtPoint(result, dummyPoint);

			(*iter)->WhereIntersects(ray, result);
			if (result.DoesIntersect())
			{
				result.ExtraInfoDouble = count;
				return;
			}
		}
	}

	result.Set(this);
}

void TexturedBox::ColorAtIntersection(SecondIntersectionResult& result, const Point& point, const Ray& ray)
{
	_rectangles[(unsigned)result.ExtraInfoDouble]->ColorAtIntersection(result, point, ray);
}

Direction TexturedBox::NormalAtPoint(FirstIntersectionResult& result, const Point& point)
{
	return _rectangles[(unsigned)result.ExtraInfoDouble]->NormalAtPoint(result, point);
}